package class_loader;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;

import org.omg.CosNaming.IstringHelper;

public class MyClassLoader extends ClassLoader {

	public final String[] classPath;

	public MyClassLoader(String classPath[]) {
		this.classPath = classPath;
	}

	@Override
	protected synchronized Class loadClass(String name, boolean resolve)
			throws ClassNotFoundException {
		Class result = findClass(name);
		String tempFileName = name.replace('.', '/');
		String javaFileName = tempFileName + ".java";
		if (name.equals("class_loader.TestModule")) {
			if (!compile(javaFileName)) {
				throw new ClassNotFoundException("Compile failed!");
			}
		}
		if (resolve) {
			resolveClass(result);
		}
		return result;
	}

	protected Class findClass(String name) throws ClassNotFoundException {
		Class result = null;
		File file = findFile(name.replace('.', '/'), ".class");
		if (file == null) {
			return findSystemClass(name);
		}
		try {
			byte[] fileAsBytes = loadFileAsBytes(file);
			result = defineClass(null, fileAsBytes, 0, fileAsBytes.length);
		} catch (IOException e) {
			throw new ClassNotFoundException("Cannot load class " + name + "!");
		} catch (ClassFormatError e) {
			throw new ClassNotFoundException("Format of class file incorrect!");
		}
		return result;
	}

	private File findFile(String name, String extension) {
		for (int k = 0; k < classPath.length; k++) {
			File file = new File(new File(classPath[k]).getPath()
					+ File.separatorChar
					+ name.replace('/', File.separatorChar) + extension);
			if (file.exists()) {
				return file;
			}
		}
		return null;
	}

	private byte[] loadFileAsBytes(File file) throws IOException {
		byte[] result = new byte[(int) file.length()];
		FileInputStream is = new FileInputStream(file);
		try {
			is.read(result, 0, result.length);
		} finally {
			try {
				is.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	protected URL findResource(String name) {
		File f = findFile(name, "");
		if (f == null)
			return null;
		try {
			return f.toURL();

		} catch (MalformedURLException e) {
			return null;
		}
	}

	private boolean compile(String fileName) {
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		int result = compiler.run(null, null, null, new String[] {
				"-d",
				"/home/muzv/epam_pre_prod/workspace/ClassLoader/bin/",
				"/home/muzv/epam_pre_prod/workspace/ClassLoader/src/"
						+ fileName });
		return result == 0;
	}
}
